package com.rj.ability.leqi.client;

import com.fasterxml.jackson.core.type.TypeReference;
import com.rj.ability.leqi.common.*;
import com.rj.core.algorithm.AlgorithmUtils;
import com.rj.util.AssertBeanUtils;
import com.rj.util.ByteUtils;
import com.rj.util.JsonUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 乐企开票平台客户端
 *
 * @author YFX_RANLUBO
 * @date 2024/04/30 15:22
 **/
@Slf4j
public class LqptApiService {
    @Resource
    private LqptApiClient lqptApiClient;
    /**
     * 当前处理的所对应的用户信息
     */
    @Resource
    public BaseLeqiInfoConfig baseLeqiInfoConfig;
/*    @Resource
    public ILqptApiServiceEvent apiServiceEvent;*/
    /**
     * 业务请求接口模板
     */
    private static final String REQ_URL_TPL = "/access%sv2/invoke/%s/%s";
    /**
     * 沙箱控制访问接口模板
     */
    private static final String KZFW_URL_TPL = "/access/sandbox_kzfw/v1/%s";

   /* public CommonResp execute(CommonReq req) {
        if (baseLeqiInfoConfig == null) {
            return fail("平台配置未初始化");
        }
        String reqId = req.getRequest_id();
        //1.查找服务枚举
        LeqiEnum serviceEnum = findDest(req.getName());
        //2.转换请求内容
        AbstactAisinoLeqiHandler handler = serviceEnum.getHandler();
        AisinoTaxpayerReq aisinoReq = (AisinoTaxpayerReq) req.parse(handler.getReqClazz());
        //3.获取用户信息
        BaseUserInfo baseUserInfo = null;
        if (aisinoReq.getTaxpayerID() != null) {
            baseUserInfo = baseLeqiInfoConfig.queryBaseUserInfo(aisinoReq.getTaxpayerID());
        }
        //4.将航信请求转换为乐企请求
        handler.setBaseLeqiInfoConfig(baseLeqiInfoConfig);
        Object lqReq = handler.convert(aisinoReq);
        BeforeEvent beforeEvent = new BeforeEvent(serviceEnum, aisinoReq, lqReq, req, baseLeqiInfoConfig, baseUserInfo, this);
        apiServiceEvent.beforeHandler(beforeEvent);
        //5.发起乐企开票请求
        CommonResp commonResp = null;
        if (beforeEvent.isSend_http()) {
            ComReq comreq = new ComReq(serviceEnum.getJkbm(), lqReq, serviceEnum.getApiType(), req.getRequest_id());
            LeqiCommonResponse leqiRes = execute(comreq, baseUserInfo, serviceEnum.getApiType());
            //6.乐企结果解析
            commonResp = leqiCommonResponseHandler(leqiRes, handler.getTargetResClazz(), (data) -> handler.successHandler(data, lqReq, aisinoReq));
        } else {
            commonResp = success("成功").setResult(handler.successHandler(null, lqReq, aisinoReq));
        }

        apiServiceEvent.afterHandler(new AfterEvent(serviceEnum, commonResp));
        return commonResp.setData(commonResp.getResult()).setRequest_id(reqId);
    }*/

/*    private LeqiEnum findDest(String name) {
        for (LeqiEnum leqiEnum : LeqiEnum.values()) {
            if (leqiEnum.getServiceName().equals(name)) {
                return leqiEnum;
            }
        }
        AssertUtils.throwException("未找到对应服务名%s", name);
        return null;
    }*/

    /**
     * 乐企接口数据请求
     */
    public <T extends BizSuccessCommonRes> LeqiCommonResponse execute(ComReq comReq, BaseUserInfo baseUserInfo,
                                                                      ApiTypeEnum tdyhApiTypeEnum) {
        if (baseUserInfo == null) {
            log.warn("BaseUserInfo为空》》》{}", this.getClass());
        }
        //确定访问能力
        ApiTypeEnum apiTypeEnum = comReq.getApiTypeEnum();
        if (apiTypeEnum.equals(ApiTypeEnum.KP_JCNL)) {
            if (tdyhApiTypeEnum != null) {
                apiTypeEnum = tdyhApiTypeEnum;
            }
        }
        //确定地址
        String url;
        if (ApiTypeEnum.SANDBOX_KZFW.equals(apiTypeEnum)) {
            url = KZFW_URL_TPL.formatted(comReq.getJkbm());
        } else {
            url = REQ_URL_TPL.formatted(baseLeqiInfoConfig.getSandbox() ? "/sandbox/" : "/", apiTypeEnum.getNlbm(), comReq.getJkbm());
        }
        //数据加密
        String data = JsonUtil.toString(comReq.getData());
        byte[] encData = AlgorithmUtils.Sm.sm4(ByteUtils.getBytes(baseLeqiInfoConfig.getKey())).encrypt(data);
        //发起访问
        return lqptApiClient.execute(baseLeqiInfoConfig.getBaseUrl() + url, getHeaders(baseUserInfo, apiTypeEnum),
                        ByteUtils.toString(encData))
                .setReqId(comReq.getReqId());
    }

    /**
     * 结果解析
     * @param res 乐企响应结果
     * @param leqRes 乐企响应结果类型处理器
     * @param successHandler 业务成功处理器将乐企结果转换为业务结果
     * @param <Res>
     * @return
     */
    public <Res> Res leqiCommonResponseHandler(LeqiCommonResponse res,
                                               TypeReference<BizSuccessCommonRes> leqRes,
                                               Function<BizSuccessCommonRes, Res> successHandler) {
        String body = res.getBody();
        if (res.isSuccess()) {
            BodySuccess success = JsonUtil.toObject(body, BodySuccess.class);
            Response response = success.getResponse();
            String data = response.getData();
            if (data == null) {
                BizFailRes error = response.getError();
                AssertBeanUtils.throwException("局端异常>>代码:{},原因:{}", error.getCode(), error.getMessage());
            }
            //业务成功数据解密
            BizSuccessCommonRes result = response.decryptData(baseLeqiInfoConfig.getKey(), leqRes);
            if (result.isSuccess()) {
                return successHandler.apply(result);
            }
            AssertBeanUtils.throwException("局端提示业务内部处理错误code:{};msg:{}", result.getCode(), result.getMessage());
        }
        try {
            BodyError error = JsonUtil.toObject(body, new TypeReference<>() {});
            //正常错误提示
            AssertBeanUtils.throwException("局端提示接口请求错误:{};msg:{}", error.getCode(), error.getMessage());
        } catch (Exception e) {
            //不是错误结构，局端服务响应异常
            AssertBeanUtils.throwException("局端服务响应异常:{};msg:{}", res.getHttpStatusCode(), body);
        }
        return null;
    }

    /**
     * 设置请求头
     *
     * @param baseUserInfo
     * @param apiTypeEnum
     * @return
     */
    private Map<String, String> getHeaders(BaseUserInfo baseUserInfo, ApiTypeEnum apiTypeEnum) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=UTF-8");
        headers.put("Accept", "application/json");
        headers.put("jrdwptbh", baseLeqiInfoConfig.getJrdwptbh());
        headers.put("sydwptbh", baseUserInfo.getSydwptbh());
        headers.put("nlbm", apiTypeEnum.getNlbm());
        headers.put("access_signature", "");
        if (baseLeqiInfoConfig.getSandbox()) {
            boolean zt = baseLeqiInfoConfig.queryAbilityZt(apiTypeEnum);
            headers.put("sxcsbz", zt ? "1" : "");
            String ylbm = apiTypeEnum.getYlbm();
            if (ylbm != null && zt == false) {
                headers.put("ylbm", ylbm);
            }
        }
        return headers;
    }


}